package com.fau.hm.service.impl;

import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.validation.ConstraintViolation;

import org.apache.commons.lang3.StringUtils;
import org.hibernate.Hibernate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.fau.hm.entity.MedicalAdmin;
import com.fau.hm.entity.MedicalArchivalInfo;
import com.fau.hm.entity.MedicalKeyValue;
import com.fau.hm.service.IArchivalManagerService;
import com.fau.hm.util.Page;
import com.fau.hm.util.ParamUtil;
import com.fau.hm.util.SystemConfig;
import com.fau.hm.util.ValidatorUtil;

@Service
@Transactional(readOnly = true)
public class ArchivalManagerService extends BaseService implements IArchivalManagerService {

	@Override
	public Page findArchivalList(Map<String, Object> map, MedicalArchivalInfo info, MedicalAdmin admin) {
		StringBuilder statusSql = new StringBuilder("from MedicalArchivalInfo a where 1=1 and a.user.enterpriseId = ? ");
		StringBuilder countSql = new StringBuilder("select count(*) from MedicalArchivalInfo a where 1=1 and a.user.enterpriseId = ? ");
		
		List<Object> objectList = new ArrayList<Object>();
		objectList.add(admin.getEnterpriseId());
		
		if(StringUtils.isNotBlank(info.getName())){
			String str = info.getName().trim().replaceAll("_", "chr(95)").replaceAll("%", "chr(37)");
			statusSql.append(" and a.user.name like ? ");
			countSql.append(" and a.user.name like ? ");
			objectList.add("%"+str+"%");
		}
		
		if(StringUtils.isNotBlank(info.getDeptType())){
			String[] str = info.getDeptType().split(",");
			statusSql.append(" and (a.user.deptType = ? ");
			countSql.append(" and (a.user.deptType = ? ");
			objectList.add(str[0]);
			if(str.length > 1){
				for(int i=1;i<str.length;i++){
					statusSql.append(" or a.user.deptType = ? ");
					countSql.append(" or a.user.deptType = ? ");
					objectList.add(str[i]);
				}
			}
			statusSql.append(")");
			countSql.append(")");
		}
		
		if(StringUtils.isNotBlank(info.getGroupIds())){
			String[] str = info.getGroupIds().split(",");
			statusSql.append(" and (a.user.group.id = ? ");
			countSql.append(" and (a.user.group.id = ? ");
			objectList.add(str[0]);
			if(str.length > 1){
				for(int i=1;i<str.length;i++){
					statusSql.append(" or a.user.group.id = ? ");
					countSql.append(" or a.user.group.id = ? ");
					objectList.add(str[i]);
				}
			}
			statusSql.append(")");
			countSql.append(")");
		}
		
		//排序
		String[] sortField = (String[]) map.get("sortField");
		String[] sortOrder = (String[]) map.get("sortOrder");
		if(StringUtils .isNotBlank(sortField[0]) && StringUtils.isNotBlank(sortOrder[0])){
			statusSql.append("order by a." + sortField[0] + " " + sortOrder[0]); 
		} else {
			statusSql.append("order by a.createTime desc ");
		}

		Page page = this.iBaseDao.getPage(ParamUtil.getInteger(map,"pageIndex",1),ParamUtil.getInteger(map, "pageSize", 20),
				map, countSql.toString(), statusSql.toString(), objectList);
		List<MedicalArchivalInfo> infoList = new ArrayList<MedicalArchivalInfo>();
		for(Object obj : page.getResult()){
			MedicalArchivalInfo bean = (MedicalArchivalInfo) obj;
			MedicalKeyValue keyValue = this.iBaseDao.getValueByKey(admin.getEnterpriseId(), SystemConfig.HM_SYSTEM_TYPE, bean.getGender());
			if(null != keyValue){
				bean.setGenderName(keyValue.getKeyValue());
			}
			MedicalKeyValue dept = this.iBaseDao.getValueByKey("0", SystemConfig.HM_SYSTEM_TYPE, bean.getUser().getDeptType());
			bean.getUser().setDeptName(dept.getKeyValue());
			if(SystemConfig.CM_SYSTEM_TYPE.equals(bean.getUser().getDeptType()) || SystemConfig.OM_SYSTEM_TYPE.equals(bean.getUser().getDeptType())) {
				Hibernate.initialize(bean.getUser().getGroup());
			}
			infoList.add(bean);
		}
		return page;
	}

	@Override
	@Transactional(readOnly = false, propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	public boolean save(MedicalArchivalInfo info) {
		MedicalAdmin user = new MedicalAdmin();
		user.setId(info.getUserId());
		info.setUser(user);
		Set<ConstraintViolation<Object>> errorInfo = ValidatorUtil.validateObj(info);
		if(errorInfo.size() > 0) {
			return false;
		} else {
			return this.iBaseDao.saveObject(info);
		}
	}

	@Override
	@Transactional(readOnly = false, propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	public boolean update(MedicalArchivalInfo info) {
		MedicalArchivalInfo bean = (MedicalArchivalInfo) this.iBaseDao.getObject(MedicalArchivalInfo.class, info.getId());
		bean.setGender(info.getGender());
		bean.setIdCardNum(info.getIdCardNum());
		bean.setEntryTime(info.getEntryTime());
		bean.setContractNum(info.getContractNum());
		bean.setArchivesUrl(info.getArchivesUrl());
		bean.setUpdateTime(new Date());
		Set<ConstraintViolation<Object>> errorInfo = ValidatorUtil.validateObj(bean);
		if(errorInfo.size() > 0) {
			return false;
		} else {
			return this.iBaseDao.saveObject(bean);
		}
	}

	@Override
	public Page findAllUsers(Map<String, Object> map, MedicalArchivalInfo info) {
		StringBuilder statusSql = new StringBuilder("from MedicalAdmin a where 1=1 and a.enterpriseId = ? and a.jobStatus = ? and a.isSuper <> ? ");
		StringBuilder countSql = new StringBuilder("select count(*) from MedicalAdmin a where 1=1 and a.enterpriseId = ? and a.jobStatus = ? and a.isSuper <> ? ");
		
		List<Object> objectList = new ArrayList<Object>();
		objectList.add(info.getUser().getEnterpriseId());
		objectList.add(SystemConfig.JOB_WORK_STATUS);
		objectList.add(SystemConfig.SUPER_ADMIN);
		List<String> ids = this.findUserIds();
		if(ids.size() > 0){
			statusSql.append(" and a.id not in ( ? ");
			countSql.append(" and a.id not in ( ? ");
			objectList.add(ids.get(0));
			for(int i=1;i<ids.size();i++){
				statusSql.append(",? ");
				countSql.append(",? ");
				objectList.add(ids.get(i));
			}
			statusSql.append(")");
			countSql.append(")");
		}
		
		if(StringUtils.isNotBlank(info.getName())){
			statusSql.append(" and a.name like ? ");
			countSql.append(" and a.name like ? ");
			objectList.add("%"+info.getName()+"%");
		}
		
		statusSql.append("order by a.createTime desc ");
		
		Page page = this.iBaseDao.getPage(ParamUtil.getInteger(map,"pageIndex",1),ParamUtil.getInteger(map, "pageSize", 20),
				map, countSql.toString(), statusSql.toString(), objectList);
		List<MedicalAdmin> userList = new ArrayList<MedicalAdmin>();
		for(Object obj : page.getResult()){
			MedicalAdmin user = (MedicalAdmin) obj;
			MedicalKeyValue dept = this.iBaseDao.getValueByKey("0", SystemConfig.HM_SYSTEM_TYPE, user.getDeptType());
			user.setDeptName(dept.getKeyValue());
			if(SystemConfig.CM_SYSTEM_TYPE.equals(user.getDeptType()) || SystemConfig.OM_SYSTEM_TYPE.equals(user.getDeptType())) {
				Hibernate.initialize(user.getGroup());
			}
			userList.add(user);
		}
		page.setResult(userList);
		return page;
	}

	@SuppressWarnings("all")
	private List<String> findUserIds(){
		List<String> ids = new ArrayList<String>();
		List<MedicalArchivalInfo> infos = this.iBaseDao.getBySql("from MedicalArchivalInfo ", null, null);
		for(MedicalArchivalInfo info : infos){
			ids.add(info.getUser().getId());
		}
		return ids;
	}

	@Override
	@Transactional(readOnly = false, propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	public void deleteInfo(MedicalArchivalInfo info) {
		String[] ids = info.getId().split(",");
		if(ids.length == 1){
			this.iBaseDao.deleteObject(info);
		}else{
			for(String id : ids){
				this.iBaseDao.updateHql("delete from MedicalArchivalInfo a where a.id = ? ", id);
			}
		}
	}

	@Override
	public MedicalArchivalInfo findById(String id) {
		return (MedicalArchivalInfo) this.iBaseDao.getObject(MedicalArchivalInfo.class, id);
	}

	@Override
	public boolean archivalIsExists(String path) {
		File file = new File(path);
		return file.exists();
	}
	
}
